perm filename ADAM.EPF[UP,DOC]4 blob
sn#706392 filedate 1983-04-21 generic text, type C, neo UTF8
COMMENT ā VALID 00014 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 THE ADAM COMPILER
C00007 00003
C00010 00004
C00012 00005 Compiling a source file.
C00015 00006 Switch setting.
C00017 00007 Separate compilation and libraries.
C00021 00008
C00023 00009 Getting started using the compiler.
C00025 00010 Pragmas.
C00027 00011 Differences from standard Ada.
C00037 00012 Miscellaneous notes.
C00039 00013 Implementation notes.
C00043 00014 Predefined environment.
C00045 ENDMK
Cā;
THE ADAM COMPILER
Introduction
The Stanford Adam compiler supports a large subset of the Ada July '80
design. The subset includes packages, exceptions, generic units and
most tasking constructs; the major omissions involve numerical types.
The Adam compiler is not a validated Ada compiler.
It is intended for use in teaching Ada and experimenting with Ada tasking
programs. It employs the procedure call (or Habermann-Nassi) implementation
of tasking, which is supposedly more efficient than the rendezvous semantics
given in the Ada LRM.
The compiler also supports a simple system for manipulating libraries
for separate compilation. It has a standard environment of packages for I/O,
storage management and runtime task supervision.
It is intended to run on the DEC TOPS-20
operating system, and also runs on a PDP-10 under the
Stanford AI Lab WAITS operating system.
It produces PDP-10 assembly language code which will then run with the
standard runtime packages on TOPS-20 or WAITS.
The purpose of this document is to explain how to use the Adam compiler
and to document the differences between the Ada subset that is compiled
and Ada as defined in the July 1980 manual.
1.1 Background
The Adam compiler supports the Adam language.
Adam is an experimental language derived from Ada, and is a superset of ADA '80
. It was developed to facilitate
study of issues in Ada implementation. The two primary objectives which
motivated the development of Adam were: to program
supervisory packages for multitask scheduling, and
to formulate algorithms for compilation of Ada tasking.
Adam is a subset of the constructs of Ada
combined with a set of parallel processing constructs
which are lower level than Ada tasking.
In addition,
Adam places strong restrictions on sharing of global objects between processes.
Import declarations and propagate declarations are included.
Algorithms translating Ada tasking into Adam parallel processing
have been developed and implemented (as part of the semantic analysis
phase of the compilation). The translation implements
the procedure call method of Ada task rendezvous.
Thus the Adam compiler may be used as
an experimental compiler for most of the 1980 Ada language design,
including task types and task rendezvous constructs.
Further description of the Adam language is available in Stanford Computer
Science Report # STAN-CS-81-867. An on-line user's manual for the compiler
is available via Arpanet as <csl.ver.ada>compil.doc @SU-SCORE. The compiler
may be obtained by contacting:
Edward Falis or Dr. David Luckham
Computer Systems Lab
Stanford University
Stanford, California 94305
or by sending mail over the net to Falis @SU-SIERRA or @SU-AI, or Luckham @SU-AI.
Instructions below for Score apply for any TOPS-20 site with directory names
appropriately modified.
Compiler commands.
The compiler is invoked by typing:
r adam at SAIL, or
adam at SCORE
On SCORE, if you have no UNIQUE.NAM file in your directory, the compiler will
give you a copy of the one in the system library directory. Be sure to keep
this file in your directory between compilations to ensure compatibility.
Each time the compiler successfully completes its semantic phase, a new version
of this file will be generated. Expunge your directory occasionally to prevent
overflow if you're compiling a lot.
When invoked, the compiler prints a prompt and waits for a command to be typed.
A command to the compiler consists of a command name, or a command name
followed by a list of arguments. The number and meaning of the arguments
depends on the command name. All commands are terminated by a semicolon.
Arguments are separated by commas.
Commands can be abbreviated to a prefix of the command name.
In what follows, the valid abbreviation of command names is shown in upper case.
After a command has been executed another prompt is printed and another command
can be typed.
A <return> must be typed to terminate a command.
Underscores are represented differently on SAIL and SCORE.
The compiler maps both representations to the same character. So, either can be
used. SAIL underscores print as āX at SCORE.
File names which are used as part of a command must not be the same as an Ada
reserved word. The compiler will not recognise logically defined names (eg.
"scr:" for "<scratch>").
When the compiler is initially invoked, all file operations will be
defaulted to the job's current directory. The defaults for various
kinds of file operations can be changed by the following commands.
Alias dir-name; -- will change the default directory for all
-- operations to dir-name.
Input dir-name; -- will change the default directory for source
-- program input to dir-name.
Output dir-name; -- will change the default directory for any output
-- (excluding library modifications) which the
-- compiler generates to dir-name.
Libdir dir-name; -- will change the default directory for library
-- related i/o to dir-name.
dir-name has the form of a TOPS-20 directory name, i.e, <id {.id}> at SCORE
or p,pn at SAIL.
You must have the appropriate access rights to a directory to read or write on
it. This isn't checked by the compiler. So don't try to write into a directory
which is protected against you.
The command:
Quit; terminates the compiler.
The Help; prints a list of the available commands.
Compiling a source file.
Before any source file is compiled a library must be opened. See section on
libraries for how to do this.
To compile a source file, which is in the file, name.ada, the command is:
Compile name;
This has the following effect. The file is opened and the program is parsed.
If there is a syntax error the compiler returns to the command level.
If there are no syntax errors the static semantic checking is done.
If there are semantic errors, messages will be written to the terminal and also
to a file called name.err.
The compilation units in the source file will be inserted into the open library.
If there are no semantic errors code generation is done.
The compiler generates a file of Fail source code called name.fai.
To run a main program which is in the currently open library, the command is:
Execute main-program-name;
If no name is given as an argument, MAIN is assumed.
This command tests for completion of the compilation tree
rooted at main-program-name. If it is complete a do file is created
with a command to link the program, and the compiler terminates.
At SAIL the compiler fills the line buffer with a command to run the do file.
A <return> should be typed to run the do file.
At SCORE the name of the do file is displayed. The do file should be run by
typing:
DO file-name
to the operating system. This loads and executes the program.
ALL SOURCE FILES MUST END WITH A PERIOD. If a source file doesn't have a period
one can be typed after the compile command.
The command:
Compile; will recompile the most recently compiled file from the
current compilation session.
Switch setting.
There are various switches which can be set.
Most of the switches are used only for debugging the compiler and should not be
set. The command:
Set <switch-name> {, <switch-name>} ; turns the switch on.
Reset <switch-name> {, <switch-name>} ; turns the switch off.
(eg. "set tcg,trace,d1;" to turn on the named switches)
Switch name Effect when on Default
sem Semantic analysis is done ON
cg Code generation is done ON
seq Sequential program being compiled ON
trace Allows process interactions with the kernel to be traced OFF
checks Code is generated to test for some predefined exceptions OFF
d1 Dumps the abstract syntax tree after parsing OFF
d2 Dumps the abstract syntax tree after semantics OFF
The form dumped is specially truncated to get around the fact
that the AST is actually a DAG. Look at sy1.lsp,
function print-internal-form-new for details.
tsem Traces the semantic phase of the compiler OFF
tcg Traces the code gen phase of the compiler OFF
bsem Builtin breaks during semantic phase OFF
bcg Builtin breaks during code gen OFF
nf All output goes to terminal, no file output OFF
Separate compilation and libraries.
The compiler supports some of the Ada separate compilation facility.
A library consists of a set of compilation units.
A compilation unit can be a package specification, package body, subprogram
body, or package body subunit.
When a source file name.ada is compiled the interface information for the
units in that file is written to a file called name.ifc.
All library operations during a compilation session are done with respect to
the currently open library. Library file names have the extension .lib.
The main program is designated by having a subprogram body compilation unit
which either has the name MAIN, or has - pragma MAIN; - in its outermost
declarative part.
If a program consists of several compilation units, the main program should be
the last unit compiled before the program is run.
If the 'separate' facility is used to compile subunits, the parent unit must
be compiled before the separate subunits in order to establish the appropriate
context.
Commands for libraries.
To create a new library the command is:
CReate <library-name> [,password.<pw>]; -- this creates a file name.lib (after
-- the library is closed) in the
-- default library directory.
-- If the optional password clause
-- is included, a prompt will appear
-- at any attempt to read or open the
-- library.
To destroy a library the command is:
DEstroy <library-name>;[<pw>] -- deletes the file name.lib in the
-- default library directory.
To open an existing library the command is:
OPen <library-name>;[<pw>] -- looks for name.lib in the default
-- library directory and opens it if
-- found.
To close the currently open library the command is:
CLose;
A quit command will also close any open library.
To copy a library unit from some library to the currently open library
the command is:
COPY <library-name>.<unitname>;[<pw>] -- the .lib file extension is omitted
-- in libraryname.
Example:
OPen mylib; -- open an existing library
-- change the default library directory
-- to:
at SAIL:
Libdir lib,ada;
at SCORE: -- [lib, ada]
Libdir <csl.ver.ada> -- <csl.ver.ada>
COPY io.tty_io; -- copy a tty i/o module from io.lib
-- to mylib
To insert new compilation units into a library the procedure is:
open or create the library, and compile the units.
Example:
CReate foo;
Compile source;
The following commands can be applied to an open library.
Dir; -- list the table of contents of the library
Tdir; -- list times when units were compiled
Fdir; -- list the files from which units came and were compiled
-- into.
Wdir; -- list the 'with' requirements of the units in the library
REmove unitname; -- remove the named unit from the library.
COmplete unitname; -- tests if the compilation tree rooted at
-- unitname has been completely compiled, and
-- compiled in the correct order.
A quit command should be given to terminate the compiler to insure that library
files are updated on the disk.
Getting started using the compiler.
Most likely any simple program will need to do input or output to show
what it is doing. If you want to do terminal i/o there is an Ada package
called TTY_IO which is available. Use this package when there are no tasks
contending for the terminal. If there is contention, use DTTY_IO. To use these
packages, you should first look at the specification part of the source files
which can be found on:
TTYIOV.ADA[ENV,ADA], DTTYIO.ADA[ENV,ADA] at SAIL or
<CSL.VER.ADA>TTYIOV.ADA, <CSL.VER.ADA>DTTYIO.ADA at SCORE
There should be no need for you to compile these files because you can use
a version which is already compiled.
To do this you have to copy a library entry from an existing library which
contains it to your library.
The directories [LIB,ADA] at SAIL and <CSL.VER.ADA> at SCORE contain
a library called IO. This library contains copies of TTY_IO and DTTY_IO.
The procedure for doing this copying is described in the section on separate
compilation.
Once you have a library created (with TTY_IO or DTTY_IO in it if needed)
you can compile an Ada source file. The way to do this is described elsewhere.
Pragmas.
Pragma name Arguments Effect
TASK_TRACE none Enables tracing of task interactions
with the runtime kernel. Same effect
as the trace switch.
CALL_TRACE none When given at the top level of a
compilation, all procedure calls within
the file will be traced. Note that the
required position is after end of the
unit to be traced, and before the '.'
terminating the source file.
LINE_TRACE none When given at the top level of a
compilation, each statement executed
within the file will have its line
number and kind printed out. Required
position of the pragma is the same as
for CALL_TRACE.
CALL_TRACE list of procedure Calls to the named procedures will be
names traced. The procedures named must be
declared prior to their appearance in
the pragma.
MEMORY_SIZE integer Specifies size of stack for main
program.
HEAP_SIZE integer Specifies size of heap for accessed
objects.
STACK_HEAP_SIZE integer Specifies size of heap for task stacks.
CHECKS none Causes code to be generated for checks
for predefined exceptions. Same effect
as checks switch.
Differences from standard Ada.
If you have not made use of any of the unimplemented facilities listed
below, then
Ask FALIS @SU-SIERRA or @SU-AI
Each section contains a list of the main unimplemented features of the July '80
Ada design, and any deviations from the design. <this list is not complete>
2. LEXICAL ELEMENTS
A. Compilation units must end with a ".". Alternatively, it may be entered
directly to the compiler after the source file has been read.
3. DECLARATIONS and TYPES
A. No fixed point types.
B. Float does not have accuracy constraints.
C. Array objects cannot derive their size from an initial expression.
D. No overloading of enumeration literals.
E. Discriminant constraints must be static expressions.
F. Use Integer constants instead of number declarations (3.2) to avoid
problems in type resolution.
G. When initializing a constrained string constant, or associating an
actual parameter with a constrained formal string, no error message
will result for incompatible lengths; the value associated will be
of the same length as the constrained object, and either truncated
or filled (with garbage) to conform.
H. Compiler illegally accepts declarations of record objects with variants
and no discriminant constraint (it appears to default to having all
variant fields present).
I. RANGE attribute is unimplemented (3.6.4).
J. Compiler does not recognize a task type declaration as matching an
incomplete type declaration with the same name. eg:
type t;
...
task type t;
will not be recognised as the same type.
4. NAMES and EXPRESSIONS.
A. Aggregates should be qualifed by their type.
B. Overload resolution is done in one bottom-up pass. So the type of an
item in an expression must be determinable independent of its context.
C. The "rem" operator is unimplemented. The compiler will accept it in
the syntax and semantic phases, but will not generate correct code for
it.
D. IN operator does not work with a subtype mark as its argument,
only for explicit ranges. (4.4).
E. Index constraints on unconstrained array specifications are sometimes
ignored due to a grammar conflict in the SLR grammar used by the
compiler. The effect is that the compiler believes the array is
already constrained with index bounds of the base type.
5. STATEMENTS
A. Complete record assignment for records which have array fields which
depend on a discriminant.
6. SUBPROGRAMS
A. Actual "out" and "in out" parameters may not be type conversions .
See 4.6 in ref manual.
B. Does not accept explicit subprogram declarations anywhere except in
package specifications.
C. Contrary to section 6.7, "/=" is not implicitly overloaded when "=" is.
Note that a particularly annoying manifestation of this occurs when a
non-scalar subtype is declared, and the "/=" operator is not inherited.
7. PACKAGE
A. default generic parameters.
B. Name parameter associations in generic instantiation.
C. Deferred constants of private type.
8. VISIBILITY
A. "Use" clauses in an enclosing unit tend not to be visible to generic
formal parameter declarations: use selected notation.
9. TASKS
A. No entry families.
B. No Delay alternative in selective wait.
C. delay must be given an INTEGER expression instead of DURATION;
the expression is the number of tenths of seconds to delay.
D. No terminate alternative in selective wait.
E. Abort statement will not abort dependent tasks.
F. No entry'count.
G. priorities are 0 .. 10 with 10 being the highest priority.
Default priority is currently 5.
H. No shared variable update.
I. If the main program is ready to terminate, and there are only non-term-
inated library tasks active, the program goes to sleep.
J. Dependency of dynamically allocated task objects is not implemented.
In addition, dependencies of tasks on other tasks are sometimes
incorrectly established as dependencies on the unit declaring the
parent task.
K. No timed entry calls.
L. The number of open select alternatives for a given entry in a selective
wait is limited to 5. A predefined exception LIST_ERROR is raised if
there are more than 5 alternatives for the same entry open.
M. A maximum of 5 open accept alternatives for a given entry are allowed
in a single selective wait statement.
N. Tasks and task types declared in the visible part of a library package
do not work correctly, and the compiler will not flag this as an error
until link or run time. Basically, there is a failure in the task tran-
slation routines in making the task's entries and body visible.
10. COMPILATION UNITS.
A. A task specification and body may not be separated by separate
compilation units.
E.g., if a package specification containing a task specification
is compiled separately from the body of the package containing the task
body.
E.g., a subunit cannot be a task body.
B. Generic units cannot have subunits.
C. Generic bodies must be compiled before any instantiations of the
generic are done. (Access before elaboration is not checked here.)
11. EXCEPTIONS.
A. Propagation of unhandled exceptions from accept body to both partners
of the rendezvous. The exception is currently not propagated to the
task owning the called entry.
B. No FAILURE exception.
C. NOTE: as per the usage of the July '82 reference manual (11.1), an
exception declared in a generic unit denotes a distinct exception
for each instantiation of the unit.
12. GENERIC UNITS.
A. Type checking for conformance of formal and actual generic parameters
is weak.
STANDARD.
A. No ASCII, SYSTEM packages.
B. Control characters are enumeration literals in type CHARACTER.
Miscellaneous notes.
There is a limit on the number of tasks which can be activated.
This is determined by the amount of space allocated for task stacks and by the
number of entries in the process table of the runtime kernel.
Currently the kernel has space for 100 tasks (including the main program) to be
active at any time.
Each task is allocated a stack of size 1000 words + the size of its declarative
part.
The amount of total task stack space can be set by the pragma STACK_HEAP_SIZE.
The default value is 150000, which should be sufficient in most cases.
Task stacks are reclaimed at the time of the task's termination.
Implementation notes.
A library file consists of the name of the user who created the library,
the creation date, and a list of compilation units.
For a compilation unit the library keeps a filename pointer to the file which
has the interface information for that unit.
The interface file contains copies of the abstract syntax trees of the visible
parts of the compilation units.
The compiler assigns unique labels to entry points which occur in the
visible part of a compilation unit. Each exception is assigned a unique integer.
To generate these unique names the compiler maintains a file which records the
last values assigned. This file (UNIQUE.NAM) is updated after successful com-
pletion of the semantic checking phase of the compilation. On SCORE, each user
has his own version of this file, which is initialized above the labels and
exceptions occurring in the standard i/o and system environment packages.
On SAIL, a single file is maintained in [lib,ada].
If the LISP error:
; <space-name> STORAGE-CAPACITY-EXCEEDED
; BKPT GC-OVERFLOW
occurs, you may attempt to increase the allocation for the space using the Lisp
alloc function (see MacLisp Manual). If all else fails, or some other lisp
error such as
; BKPT GC-LOSSAGE
occurs try typing the following sequence, which will prevent you from losing
any work you've done prior to the current compile:
control-G,
(parse)
close;
The Lisp environment will print out a lot of junk, but you should be able to
save the state of your library as of before the current compile. Then reset
your Ada fork (at SCORE) and restart the compiler, reopen your library, and
continue by compiling the unit which caused the lisp error.
If a LISP IO error or DISK error occurs (Score only), chances are you
haven't enough room in your directory to write out a file. If making space
fails to correct the problem (use the recovery procedure above, and make
space before calling the compiler again), contact:
FALIS @SU-SIERRA or @SU-AI.
Predefined environment.
The compiler assumes the existence of two system interface files.
The first, seqv.ifc, contains modules for the sequential part of the language.
Currently it has:
- access type allocators, called Global_Allocator and Local_Allocator.
- a reclamable boundary tag heap allocator, called Heap_Allocator
The second, parv.ifc, contains modules for the parallel part of the language:
Currently it contains:
- the runtime kernel, called Supervisor
- condition variables, called Conditionvars
- a module supporting the implementation of selective waits.
These files should be on [lib,ada] at SAIL, and on <csl.ver.ada> at SCORE.
On these areas there are also libraries containing I/O modules, and other
modules of general interest.
The source code for these modules is currently on [env,ada] and [pkg,ada] at
SAIL.
Tasking examples may be found on [tsk,ada] at SAIL. Miscellaneous examples may
be found on <csl.ver.examples> at SCORE, [pkg,ada] at SAIL.
There must be a file on [lib,ada] and <csl.ver.ada> called unique.nam for
generating unique labels for entry points and unique integers identifying
user defined exceptions.